package org.sardine.beans;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.sardine.beans.support.BeanObjectInstantiationException;
import org.sardine.util.Assert;

public class BeanUtils {
	
	public static Object instantiateClass(Class clazz){
		Assert.notNull(clazz, "clazz 不能为 null");
		if(clazz.isInterface()){
			throw new BeanObjectInstantiationException("不能实例化接口类型："+clazz.getName());
		}
		
		Constructor constructor = null;
		try {
			constructor = clazz.getConstructor(null);
		} catch (NoSuchMethodException e) {
			throw new BeanObjectInstantiationException("找不到默认构造方法（无参数）",e);
		} catch (SecurityException e) {
			throw new BeanObjectInstantiationException("SecurityException",e);
		}
		return instantiateClass(constructor,null);
		
	}
	
	public static Object instantiateClass(Constructor constructor,Object[] args){
		
		Assert.notNull(constructor, "Constructor 不能为 null");
		Object obj = null;
		makeAccessable(constructor);
		try {
			obj =  constructor.newInstance(args);
		} catch (InstantiationException e) {
			throw new BeanObjectInstantiationException(constructor.getDeclaringClass(),"它是抽象类？",e);
		} catch (IllegalAccessException e) {
			throw new BeanObjectInstantiationException(constructor.getDeclaringClass(),"构造方法无法访问",e);
		} catch (IllegalArgumentException e) {
			throw new BeanObjectInstantiationException(constructor.getDeclaringClass(),"构造方法的参数不合法",e);
		} catch (InvocationTargetException e) {
			throw new BeanObjectInstantiationException(constructor.getDeclaringClass(),"构造方法抛出异常",e.getTargetException());
		}
		return obj;
		
	}
	
	public static void makeAccessable(Constructor constructor){
		if (!Modifier.isPublic(constructor.getModifiers()) || !Modifier.isPublic(constructor.getDeclaringClass().getModifiers())) {
			constructor.setAccessible(true);
		}
	}
	
	public static void makeAccessible(Method method) {
		if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
			method.setAccessible(true);
		}
	}
	
	

}
